SSO 登入還沒搞定不過先來嘗試當初選擇 Rocket.chat 的另一個理由,將 Rocket.chat 嵌入我們的主應用的功能。
嵌入的方式是用 iframe 來達成,首先來設定。
在 Administration → Workspace → Settings → Accounts → Iframe ,先 Enabled。
然後 Iframe URL 填準備嵌入的 Nextjs 應用網址,例:http://localhost:3000
API URL 的部分需要說明一下 Rocket.chat iframe 的認證方式,Rocket.chat 會在 iframe 載入時呼叫 API URL 確認用戶是否已登入,這部分需要在 Nextjs 這端實作。
為求快速驗證功能先做一個陽春的 sso API,直接跟 Rocket.chat 取得 token 後回傳。
// src/app/api/sso/route.ts
import axios from "axios";
export async function POST(request: Request) {
try {
const res = await axios.post("http://localhost:3001/api/v1/login", {
username: 'admin-user',
password: 'admin-user-password',
});
if (res.data.status === "success") {
return Response.json({
loginToken: res.data.data.authToken,
});
}
} catch (error) {
return Response.json({
status: 401,
});
}
}
先直接用創建 Workspace 時建立的 admin 帳號密碼經由 API 登入 Rocket.chat 取得 token 並回傳。
另外為了讓 iframe 請求 sso API 時不會被 CORS 擋住,要設定一下 Nextjs config。
// next.config.js
...
const config = {
...
async headers() {
return [
{
// matching all API routes
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{
key: "Access-Control-Allow-Origin",
value: "*", // replace this your actual Rocket.chat origin
},
{
key: "Access-Control-Allow-Methods",
value: "GET,DELETE,PATCH,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value:
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
},
],
},
];
},
};
...
然後回頭設定 Rocket.chat 的 Iframe API URL
http://localhost:3000/api/sso
這邊 sso API 寫的比較簡略,只是直接登入,不過如果用戶在 Rocket.chat 不存在也能先建立帳號後取得 token,可以看看官方的範例。
另外先關掉 Administration → Settings → General 裡的 Restrict access inside any Iframe
選項好方便 localhost 連線,正式的時候要記得開回來。
然後就能在 Nextjs 開個 iframe 來看看效果,開一個新的 chat 頁面。
// src/app/[locale]/chat/page.tsx
"use client";
const Page = () => {
return (
<>
<h1>{"Chat"}</h1>
<iframe
src="http://localhost:3001/channel/general/?layout=embedded"
title="chat"
width={400}
height={600}
></iframe>
</>
);
};
export default Page;
iframe src 的格式如下:
{rocket_chat_url}/channel/{channel_name}/?layout=embedded
layout=embedded
會讓 Rocket.chat 以單一 channel 的模式呈現。
呈現的畫面會像這樣
第一步遷入的效果看來是成功了,不過課題還很多,像是用戶驗證,樣式調整,還有選擇聊天室的介面等等。